/**
 * 项目名：化工企业安全生产信息化管理平台
 * 日期：    2020-03-01 21:14:38
 * Copyright (c) 2015- -版权所有
 */

package com.joysuch.wwyt.common.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import javax.persistence.EntityManager;
import javax.transaction.Transactional;

import com.joysuch.wwyt.common.bean.CommonTypeDetailBean;
import com.joysuch.wwyt.common.bean.CommonTypeEditBean;
import com.joysuch.wwyt.common.bean.CommonTypeListBean;
import com.joysuch.wwyt.common.bean.CommonTypeListBean.SearchCommonType;
import com.joysuch.wwyt.common.entity.CommonType;
import com.joysuch.wwyt.common.entity.dsl.QCommonType;
import com.joysuch.wwyt.common.enums.CommonTypes;
import com.joysuch.wwyt.common.repository.CommonTypeDao;
import com.joysuch.wwyt.common.service.CommonTypeService;
import com.joysuch.wwyt.core.bean.SimpleSelectListBean;
import com.joysuch.wwyt.core.common.util.PageDataUtils;
import com.joysuch.wwyt.core.common.util.PageDataUtils.PageDataConvert;
import com.joysuch.wwyt.core.exception.BusinessRestrictionsException;
import com.joysuch.wwyt.core.service.BizCodeGeneratorFacade;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Predicate;
import org.apache.shiro.util.Assert;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

@Service
@Transactional
public class CommonTypeServiceImpl implements CommonTypeService {

    @Autowired
    private CommonTypeDao dao;
    @Autowired
    private BizCodeGeneratorFacade bizCodeGeneratorFacade;
    @Autowired
    private EntityManager em;

    @Override
    public CommonType add(CommonTypeEditBean entity) {
        CommonType content = new CommonType();
        Assert.isTrue(dao.countOfName(entity.getType(), entity.getName()) == 0,
                String.format("名称%s已经存在", entity.getName()));
        // if(StringUtils.isNotBlank(entity.getCode())) {
        // Assert.isTrue(dao.countOfCode(entity.getCode()) == 0, String.format("编号%s已经存在", entity.getCode()));
        // content.setCode(entity.getCode());
        // } else {
        // content.setCode(bizCodeGeneratorFacade.commonType());
        // }
        BeanUtils.copyProperties(entity, content, "id", "code");
        content.setObjCount(0);
        return dao.save(content);
    }

    @Override
    public void   update(CommonTypeEditBean entity) {
        CommonType content = dao.findById(entity.getId()).get();
        Assert.isTrue(dao.countOfNameExcludeId(entity.getType(), entity.getName(), entity.getId()) == 0,
                String.format("名称%s已经存在", entity.getName()));
        // Assert.notNull(entity.getCode(), "编号不能为空");
        // Assert.isTrue(dao.countOfCodeExcludeId(entity.getCode(), entity.getId()) == 0, String.format("编号%s已经存在",
        // entity.getCode()));
        // content.setCode(entity.getCode());
        BeanUtils.copyProperties(entity, content, "id", "code", "type");
        content.setObjCount(countOf(entity.getId(), entity.getType()));
        dao.save(content);
    }

    @Override
    public void updateTypeCount(CommonTypes type, Long typeId) {
        if (typeId == null) {
            return;
        }
        dao.findById(typeId).ifPresent(ct -> {
            ct.setObjCount(countOf(type.getEntityClass(), type.getTypeFieldName(), typeId));
            dao.save(ct);
        });
    }

    private Integer countOf(Long id, String type) {
        CommonTypes ct = CommonTypes.findByName(type);
        if (ct != null) {
            return countOf(ct.getEntityClass(), ct.getTypeFieldName(), id);
        }
        return 0;
    }

    private Integer countOf(Class entityClass, String relateFieldName, Long typeId) {
        String jql = "select count(m) from " + entityClass.getName() + " m where " + relateFieldName + " = " + typeId;
        return ((Number) em.createQuery(jql).getSingleResult()).intValue();
    }

    @Override
    public Page<CommonTypeListBean> findByPage(Pageable page, SearchCommonType condition) {
        Predicate predicate = prepareListSearchCondition(condition);

        Page<CommonType> data = predicate == null ? dao.findAll(page) : dao.findAll(predicate, page);

        return PageDataUtils.convertPageData(data, new PageDataConvert<CommonTypeListBean, CommonType>() {

            @Override
            public CommonTypeListBean convert(CommonType f) {
                CommonTypeListBean bean = new CommonTypeListBean();
                BeanUtils.copyProperties(f, bean);
                bean.setNumber(f.getObjCount());
                return bean;
            }

        });
    }

    private Predicate prepareListSearchCondition(SearchCommonType condition) {
        Predicate p = null;
        QCommonType q = QCommonType.commonType;
        if (condition.getType() != null) {
            p = ExpressionUtils.and(p, q.type.eq(condition.getType()));
        }
        if (condition.getName() != null) {
            p = ExpressionUtils.and(p, q.name.contains(condition.getName()));
        }
        if (condition.getCode() != null) {
            p = ExpressionUtils.and(p, q.code.contains(condition.getCode()));
        }
        return p;
    }

    @Override
    public void delete(Long id) throws BusinessRestrictionsException {
        // 校验业务逻辑是否允许删除。如本数据被其他业务关联，删除后导致其他业务不可用。不能删除时将抛出业务异常
        checkBussinessRestrictions(id);
        dao.deleteById(id);
    }

    /**
     * 校验业务逻辑是否允许删除。如本数据被其他业务关联，删除后导致其他业务不可用
     *
     * @param id
     *            要删除的业务ID
     * @throws BussinessRestrictionsException
     *             抛出的业务异常
     */
    private void checkBussinessRestrictions(Long id) throws BusinessRestrictionsException {
        dao.findById(id).ifPresent(
                e -> Assert.isTrue(e.getObjCount() == null || e.getObjCount() == 0, "类型关联了" + e.getType() + ",不能删除"));
    }

    @Override
    public CommonType findById(Long id) {
        return dao.findById(id).orElse(null);
    }

    @Override
    public CommonTypeDetailBean getById(Long id) {
        CommonType entity = findById(id);
        if (entity == null) {
            return null;
        }
        CommonTypeDetailBean bean = new CommonTypeDetailBean();
        BeanUtils.copyProperties(entity, bean);
        return bean;
    }

    public String getNameById(Long id) {
        if (id == null) {
            return null;
        }
        Optional<CommonType> ot = dao.findById(id);
        if (ot.isPresent()) {
            return ot.get().getName();
        }
        return null;
    }

    @Override
    public List<CommonType> getNameByIds(List<Long> ids){
        List<CommonType> list = dao.findByIds(ids);
        return list;
    }

    @Override
    public List<SimpleSelectListBean> simpleList(CommonTypes ct) {
        Predicate p = QCommonType.commonType.type.eq(ct.getName());
        Iterable<CommonType> all = dao.findAll(p);
        List<SimpleSelectListBean> list = new ArrayList<SimpleSelectListBean>();
        for (CommonType t : all) {
            SimpleSelectListBean bean = new SimpleSelectListBean();
            bean.setLabel(t.getName());
            bean.setValue(t.getId());
            list.add(bean);
        }
        return list;
    }
}
